package com.iwhalecloud.bss.kite.cucc.service.pos.bo;

import com.alibaba.fastjson.JSONObject;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.enums.ActionType;
import com.iwhalecloud.bss.kite.manager.enums.InstType;
import com.iwhalecloud.bss.kite.manager.enums.RelType;
import com.iwhalecloud.bss.kite.manager.inst.KiteInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteOfferInstAcct;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteInstChange;
import com.iwhalecloud.bss.kite.manager.inst.change.KiteRelChange;
import com.iwhalecloud.bss.kite.manager.inst.graph.impl.RelEdge;
import com.iwhalecloud.bss.kite.service.ord.pos.handler.KiteBasePosSceneBO;
import com.iwhalecloud.bss.kite.service.ord.pos.handler.KitePosSceneUtils;
import com.iwhalecloud.bss.kite.service.ord.pos.handler.KitePosServiceUtils;
import com.iwhalecloud.bss.kite.service.ord.pos.vo.KitePosOfferInstAcctVO;
import com.iwhalecloud.bss.kite.service.ord.pos.vo.KitePosOfferInstVO;
import com.iwhalecloud.bss.kite.service.ord.pos.vo.KitePosOfferObjInstRelVO;
import com.iwhalecloud.bss.kite.service.ord.pos.vo.KitePosProdInstVO;
import com.ztesoft.bss.base.staticdata.CoreDataOffer;
import com.ztesoft.bss.common.util.SpringUtil;
import org.apache.commons.lang.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

public class KitePosSceneBO extends KiteBasePosSceneBO {

	public void initPosData(String sceneInstId, String offerInstId) {
		IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        // 3.获取场景实例变动信息
        List<KiteInstChange> instChgs = querySceneInstService.listInstChanges(sceneInstId);

        // 4.获取场景关系变动实例信息
        List<KiteRelChange> instRelChgs = querySceneInstService.listRelChanges(sceneInstId);

        // 6. 组装产品实例对象
        this.packageAllProdInst(instChgs, instRelChgs);

        // 7. 组装主套餐实例对象
        this.packageAllMainOfferInst(instChgs, instRelChgs, offerInstId);

        this.packageAllMemOfferInst(instChgs, instRelChgs, offerInstId);

        // 8. 组装促销销售品实例对象
        this.packageAllPromotionOfferInst(instChgs, instRelChgs);

        // 9. 组装礼包实例对象
        this.packageAllGiftOfferInst(instChgs, instRelChgs);

        // 11.根据关系变动组装套餐成员
        this.packOfferDetailForOfferInstByRelChgs(instRelChgs);

        // 根据变动信息组装套餐账户信息
        this.packageOfferInstAcct(instChgs);
	}

	/**
     * 根据关系变动设置销售品成员信息
     */
    protected void packOfferDetailForOfferInstByRelChgs(List<KiteRelChange> relChgs) {
        List<KiteRelChange> offerDetailRelChgs = KitePosServiceUtils.getRelChangesByRelType(relChgs,
            RelType.OFFER_OBJ_REL_TYPE_1000);
        offerDetailRelChgs.stream().forEach(item -> {
            if (!Objects.equals(KiteInst.ACTION_TYPE, item.getFieldName()) || Objects.isNull(item.getSourceInstType())) {
                return;
            }
            // 获取A端套餐实例
            KitePosOfferInstVO instVo = this.getKitePosOfferInstVOByInstTypeAndInstId(item.getSourceInstType(),
                item.getSourceInstId());
            if (!Objects.isNull(instVo)) {
                KitePosOfferObjInstRelVO posOfferObjInstRelVO = this.generateKitePosOfferObjInstRelVOByRelChg(item);
                if (posOfferObjInstRelVO != null) {
                    this.addOfferObjInstRelVO(instVo, posOfferObjInstRelVO);
                }

            }
        });
    }

    /**
     * 根据销售品明细关系变动组装生成销售品包含对象
     */
    private KitePosOfferObjInstRelVO generateKitePosOfferObjInstRelVOByRelChg(KiteRelChange relChg) {
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        KitePosOfferObjInstRelVO instVO = new KitePosOfferObjInstRelVO();
        // 设置包含对象ID,取目标对象实例ID
        instVO.setInstId(relChg.getTargetInstId());

        // 设置包含对象类型(目前不考虑账户级成员)
        String objType = Objects.equals(relChg.getSourceInstType(), InstType.GIFT_OFFER_INST)
            ? CoreDataOffer.OFF_C_0043_110000 : CoreDataOffer.OFF_C_0043_100000;

        if (Objects.equals(relChg.getSourceInstType(), InstType.GIFT_OFFER_INST)
            && Objects.equals(relChg.getTargetInstType(), InstType.PROD_INST)) {
            objType = CoreDataOffer.OFF_C_0043_100000;
        }
        instVO.setObjType(objType);

        // 设置关系动作类型
        String actionType = Objects.equals(relChg.getNewValue(), KeyConsts.ACTION_TYPE_D) ? KeyConsts.ACTION_TYPE_O
            : relChg.getNewValue();
        if (Objects.equals(actionType, KeyConsts.ACTION_TYPE_O)) {
            if (KiteStringUtils.equals(objType, CoreDataOffer.OFF_C_0043_100000)) {
                KitePosProdInstVO kitePosProdInstVO = this.getProdInstMap().get(relChg.getTargetInstId());
                if (kitePosProdInstVO == null) {
                    return null;
                }
                actionType = Objects.equals(kitePosProdInstVO.getActionType(),
                    KeyConsts.ACTION_TYPE_D) ? KeyConsts.ACTION_TYPE_D : actionType;
            }
            else if (KiteStringUtils.equals(objType, CoreDataOffer.OFF_C_0043_110000)) {
                KitePosOfferInstVO kitePosOfferInstVO = this.getOfferInstMapByInstType(relChg.getTargetInstType())
                    .get(relChg.getTargetInstId());
                if (kitePosOfferInstVO == null) {
                    return null;
                }
                actionType = Objects.equals(kitePosOfferInstVO.getActionType(), KeyConsts.ACTION_TYPE_D) ? KeyConsts.ACTION_TYPE_D
                        : actionType;
            }

        }
        instVO.setActionType(actionType);

        // 设置成员角色ID
        RelEdge relEdge = querySceneInstService.getInstRel(this.getCustId(), relChg.getSourceInstType(),
            relChg.getSourceInstId(), relChg.getTargetInstType(), relChg.getTargetInstId(), relChg.getRelType());
        instVO.setRoleId(Optional.ofNullable(relEdge).map(i -> i.getRoleId()).orElse(""));
        // 设置成员规格ID
        instVO.setSpecId(Optional.ofNullable(this.getProdInstMap().get(relChg.getTargetInstId()))
            .map(m -> m.getProdInst()).map(m -> m.getProdId()).orElse(""));
        if (KiteStringUtils.isEmpty(instVO.getSpecId())) {
            instVO.setSpecId(Optional.ofNullable(this.getMainOfferInstMap().get(relChg.getTargetInstId()))
                .map(m -> m.getOfferInst()).map(m -> m.getOfferId()).orElse(""));
        }
        if (KiteStringUtils.equals(CoreDataOffer.OFF_C_0043_110000, objType)) {
            instVO.setCatagoryId(Optional.ofNullable(OfferCache.get(instVO.getSpecId())).map(Offer::getCateId).orElse(""));
        }
        return instVO;
    }

	/**
     * 根据实例变动、关系变动组装礼包对象<br>
     * 礼包成员依赖主套餐、促销，放到最后组装<br>
     */
    protected void packageAllGiftOfferInst(List<KiteInstChange> instChgs, List<KiteRelChange> instRelChgs) {
        // 根据实例变动组装礼包套餐销售品转单对象
        this.packageAllOfferInstByInstChgsAndInstType(instChgs, InstType.GIFT_OFFER_INST);

        this.packageAllOffernstByRelChgsAndInstType(instRelChgs, InstType.GIFT_OFFER_INST);
    }

	/**
     * 根据实例变动、关系变动组装促销套餐对象<br>
     */
    protected void packageAllPromotionOfferInst(List<KiteInstChange> instChgs, List<KiteRelChange> instRelChgs) {
        // 根据实例变动组装促销套餐销售品转单对象
        this.packageAllOfferInstByInstChgsAndInstType(instChgs, InstType.PROMOTION_OFFER_INST);

        this.packageAllOffernstByRelChgsAndInstType(instRelChgs, InstType.PROMOTION_OFFER_INST);
    }

	/**
     * 根据实例变动、关系变动组装主套餐对象<br>
     */
    protected void packageAllMainOfferInst(List<KiteInstChange> instChgs, List<KiteRelChange> instRelChgs, String offerInstId) {
        // 根据实例变动组装主套餐销售品转单对象
        this.packageAllOfferInstByInstChgsAndInstType(instChgs, InstType.MAIN_OFFER_INST);

        // 根据关系变动组装套餐销售品转单对象
        this.packageAllOffernstByRelChgsAndInstType(instRelChgs, InstType.MAIN_OFFER_INST);

        // 批量受理只保留当前记录的主套餐
        if (KiteStringUtils.isNotEmpty(offerInstId)) {
            Map<String, KitePosOfferInstVO> offerInstMap = this.getOfferInstMapByInstType(InstType.MAIN_OFFER_INST);
            KitePosOfferInstVO offerInstVO = offerInstMap.get(offerInstId);
            offerInstMap.clear();
            offerInstMap.put(offerInstId, offerInstVO);
        }
    }

    /**
     * 根据实例变动、关系变动组装主套餐对象<br>
     */
    protected void packageAllMemOfferInst(List<KiteInstChange> instChgs, List<KiteRelChange> instRelChgs, String offerInstId) {
        // 根据实例变动组装主套餐销售品转单对象
        this.packageAllOfferInstByInstChgsAndInstType(instChgs, InstType.MEM_OFFER_INST);

        // 根据关系变动组装套餐销售品转单对象
        this.packageAllOffernstByRelChgsAndInstType(instRelChgs, InstType.MEM_OFFER_INST);

        // 批量受理只保留当前记录的主套餐
        if (KiteStringUtils.isNotEmpty(offerInstId)) {
            Map<String, KitePosOfferInstVO> offerInstMap = this.getOfferInstMapByInstType(InstType.MEM_OFFER_INST);
            KitePosOfferInstVO offerInstVO = offerInstMap.get(offerInstId);
            offerInstMap.clear();
            offerInstMap.put(offerInstId, offerInstVO);
        }
    }

    /**
     * 根据关系变动和实例类型组装转单销售品实例对象
     */
    private void packageAllOffernstByRelChgsAndInstType(List<KiteRelChange> instRelChgs, InstType instType) {
        // 获取销售品实例作为A端关系变动
        List<KiteRelChange> aRelChgs = KitePosServiceUtils.getRelChangesBySourceInstType(instRelChgs, instType);
        aRelChgs.stream().forEach(item -> {
            this.packageModOfferInstByInstIdAndInstType(item.getSceneInstId(), item.getSourceInstId(), instType);
        });

        // 获取销售品实例作为Z端关系变动
        List<KiteRelChange> zRelChgs = KitePosServiceUtils.getRelChangesByTargetInstType(instRelChgs, instType);
        zRelChgs.stream().forEach(item -> {
            this.packageModOfferInstByInstIdAndInstType(item.getSceneInstId(), item.getTargetInstId(), instType);
        });
    }

    /**
     * 根据关系变动和类型组装修改销售品实例对象
     */
    private KitePosOfferInstVO packageModOfferInstByInstIdAndInstType(String sceneInstId, String instId, InstType instType) {
        Map<String, KitePosOfferInstVO> instVoMap = this.getOfferInstMapByInstType(instType);
        if (!instVoMap.containsKey(instId)) {
            // 不存在则场景实例变动
            KitePosOfferInstVO instVo = com.iwhalecloud.bss.kite.cucc.service.pos.handler.
                KitePosSceneUtils.generateKitePosOfferInstVOByInstId(sceneInstId, this.getCartId(), this.getCustId(), instId);
            instVo.setActionType(ActionType.M.name());
            instVoMap.put(instId, instVo);
            return instVo;
        }
        else {
            return instVoMap.get(instId);
        }
    }

    /**
     * 根据实例变动和实例类型组装销售品实例变动
     */
    private void packageAllOfferInstByInstChgsAndInstType(List<KiteInstChange> instChgs, InstType instType) {
        List<KiteInstChange> offerInstChgs = KitePosServiceUtils.getInstChangesByInstType(instChgs, instType);

        // 根据产品实例ID分组处理构造接入产品实例对象
        for (KiteInstChange instChange : offerInstChgs) {
            Map<String, KitePosOfferInstVO> offerInstMap = this.getOfferInstMapByInstType(instType);
            KitePosOfferInstVO instVo = offerInstMap.get(instChange.getSubInstId());
            if (Objects.isNull(instVo)) {
                // 不存在则场景实例变动
                instVo = com.iwhalecloud.bss.kite.cucc.service.pos.handler.KitePosSceneUtils.generateKitePosOfferInstVOByInstId(instChange.getSceneInstId(), this.getCartId(), this.getCustId(),
                    instChange.getSubInstId());
                offerInstMap.put(instChange.getSubInstId(), instVo);
            }
            // 计算动作
            KitePosServiceUtils.computeInstAction(instVo, instChange);
            // 处理实例变动信息
            KitePosServiceUtils.dealPosInstAttr(instVo, instChange);
        }
    }

	/**
     * 根据变动组装产品实例对象集合
     */
    protected void packageAllProdInst(List<KiteInstChange> instChgs, List<KiteRelChange> instRelChgs) {
        // 通过实例变动组装产品实例
        this.packageAllProdInstByInstChgs(instChgs);

        // 通过关系变动组装产品实例
        this.packageAllProdInstByRelChgs(instRelChgs);
    }

    /**
     * 根据实例变动组装产品实例
     */
    private void packageAllProdInstByInstChgs(List<KiteInstChange> instChgs) {
        List<KiteInstChange> prodInstChgs = KitePosServiceUtils.getInstChangesByInstType(instChgs, InstType.PROD_INST);

        // 根据产品实例ID分组处理构造接入产品实例对象
        for (KiteInstChange instChange : prodInstChgs) {
            KitePosProdInstVO instVo = this.getProdInstMap().get(instChange.getSubInstId());
            if (Objects.isNull(instVo)) {
                // 不存在则场景实例变动
                instVo = com.iwhalecloud.bss.kite.cucc.service.pos.handler.KitePosSceneUtils
                    .generateKitePosProdInstVOByInstId(instChange.getSceneInstId(), this.getCartId(), this.getCustId(), instChange.getSubInstId());
                //虚拟产品实例不拼
                if (!Objects.isNull(instVo.getProdInst().getIsVirtualInst()) && instVo.getProdInst().getIsVirtualInst()
                    .equals(Boolean.TRUE)) {
                    continue;
                }
                this.getProdInstMap().put(instChange.getSubInstId(), instVo);
            }
            // 计算动作
            KitePosServiceUtils.computeInstAction(instVo, instChange);
            // 处理实例变动信息
            KitePosServiceUtils.dealPosInstAttr(instVo, instChange);
        }
    }

    /**
     * 根据关系变动组装转单产品实例对象
     */
    private void packageAllProdInstByRelChgs(List<KiteRelChange> instRelChgs) {
        // 获取接入产品实例作为A端关系变动
        List<KiteRelChange> aRelChgs = KitePosServiceUtils.getRelChangesBySourceInstType(instRelChgs,
            InstType.PROD_INST);
        aRelChgs.stream().forEach(item -> {
            if (Objects.nonNull(item) && Objects.equals(KiteInst.ACTION_TYPE, item.getFieldName())
                && !Objects.equals(item.getNewActionType(), ActionType.X)) {
                this.packageModProdInstByInstId(item.getSceneInstId(), item.getSourceInstId());
            }
        });

        // 获取接入产品实例作为Z端关系变动
        // 如果关系为群组关系，z端不组装产品实例
        List<KiteRelChange> zRelChgs = KitePosServiceUtils.getRelChangesByTargetInstType(instRelChgs,
            InstType.PROD_INST);
        zRelChgs.stream().forEach(item -> {
            if (Objects.nonNull(item) && Objects.equals(KiteInst.ACTION_TYPE, item.getFieldName())
                && !Objects.equals(item.getNewActionType(), ActionType.X)
                && !StringUtils.startsWith(item.getRelType().getCode(), RelType.PROD_REL_TYPE)) {
                this.packageModProdInstByInstId(item.getSceneInstId(), item.getTargetInstId());
            }
        });
    }

    /**
     * 根据关系变动组装单个修改产品实例
     */
    private KitePosProdInstVO packageModProdInstByInstId(String sceneInstId, String instId) {
        if (!this.getProdInstMap().containsKey(instId)) {
            // 不存在则场景实例变动
            KitePosProdInstVO instVo = com.iwhalecloud.bss.kite.cucc.service.pos.handler.
                KitePosSceneUtils.generateKitePosProdInstVOByInstId(sceneInstId, this.getCartId(), this.getCustId(), instId);
            // 过滤无效的产品实例
            if (instVo.getProdInst() != null && !Objects.equals(instVo.getProdInst().getActionType(), ActionType.X)) {
                instVo.setActionType(ActionType.M.name());
                this.getProdInstMap().put(instId, instVo);
                return instVo;
            }
            else {
                return null;
            }
        }
        else {
            return this.getProdInstMap().get(instId);
        }
    }

    /**
     * 账户级销售品
     * @param instChgs
     */
    private void packageOfferInstAcct(List<KiteInstChange> instChgs) {
        String custId = this.getCustId();
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        //获取套餐账户变动信息
        List<KiteInstChange> instChanges = instChgs.stream().filter(kiteInstChange -> kiteInstChange.getSubInstType() == InstType.OFFER_INST_ACCT).collect(Collectors.toList());
        instChanges.forEach(kiteInstChange -> {
            //获取边和套餐级账户实例
            RelEdge relEdge = querySceneInstService
                .getInstRel(custId, kiteInstChange.getInstType(), kiteInstChange.getInstId(),
                    kiteInstChange.getSubInstType(), kiteInstChange.getSubInstId(), RelType.OFFER_OBJ_REL_TYPE_170000);
            KiteOfferInstAcct offerInstAcct = querySceneInstService.getKiteInst(custId, kiteInstChange.getSubInstType(), kiteInstChange.getSubInstId());
            if (relEdge != null && offerInstAcct != null) {
                KitePosOfferInstAcctVO posOfferInstAcct = new KitePosOfferInstAcctVO();
                posOfferInstAcct.setDetailId(relEdge.getDetailId());
                posOfferInstAcct.setRoleId(relEdge.getRoleId());
                posOfferInstAcct.setActionType(kiteInstChange.getActionType().name());
                posOfferInstAcct.setOfferInstAcct(offerInstAcct);
                this.addKitePosOfferInstAcctVO(kiteInstChange.getInstId(), posOfferInstAcct);
            }
        });
    }

	public void doTransfer() {

	}

	public void cleanScene() {
	}
}
